package cn.bytepulse.web.admin.service.impl;

import cn.bytepulse.pojo.AjaxResult;
import cn.bytepulse.web.admin.service.SystemInfoService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import oshi.SystemInfo;
import oshi.hardware.CentralProcessor;
import oshi.hardware.GlobalMemory;
import oshi.hardware.HardwareAbstractionLayer;
import oshi.hardware.NetworkIF;
import oshi.software.os.OperatingSystem;

import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.MemoryUsage;
import java.lang.management.RuntimeMXBean;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.text.SimpleDateFormat;
import java.util.*;

import static cn.bytepulse.utils.DateUtils.getTimeStr;
import static cn.bytepulse.utils.GenerateUtils.formatBytes;

/**
 * @author jiejiebiezheyang
 * @since 2024-07-12 10:00
 */
@Service
@Transactional
public class SystemInfoServiceImpl implements SystemInfoService {

    /**
     * 静态信息
     */
    @Override
    public AjaxResult fetch() throws UnknownHostException {
        SystemInfo si = new SystemInfo();
        // 操作系统信息
        OperatingSystem os = si.getOperatingSystem();
        String systemName = os.toString(); // 系统名
        String hostName = os.getNetworkParams().getHostName(); // HostName
        long upTime = os.getSystemUptime(); // 系统运行时长
        // 硬件
        HardwareAbstractionLayer hal = si.getHardware();
        // 网络
        String ipv4 = ""; // IP地址
        List<NetworkIF> networkIFs = hal.getNetworkIFs();
        for (NetworkIF anIf : networkIFs) {
            String[] iPv4addr = anIf.getIPv4addr();
            ipv4 = String.join(",", Arrays.asList(iPv4addr));
        }
        // cpu
        CentralProcessor cpu = hal.getProcessor();
        String cpuName = si.getHardware().getProcessor().getProcessorIdentifier().getName(); // cpu名称
        int physicalCoreCount = cpu.getPhysicalProcessorCount(); // 物理核心数
        int logicalCoreCount = cpu.getLogicalProcessorCount(); // 逻辑核心数
        long maxFrequency = cpu.getMaxFreq();
        String maxFrequencyStr = (maxFrequency / 1_000_000) + " MHz"; // 最大频率
        // 获取CPU使用率
        long[] prevTicks = cpu.getSystemCpuLoadTicks();
        try {
            Thread.sleep(1000); // 暂停一秒以便获取使用率
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        long[] ticks = cpu.getSystemCpuLoadTicks();
        long user = ticks[CentralProcessor.TickType.USER.getIndex()] - prevTicks[CentralProcessor.TickType.USER.getIndex()];
        long nice = ticks[CentralProcessor.TickType.NICE.getIndex()] - prevTicks[CentralProcessor.TickType.NICE.getIndex()];
        long system = ticks[CentralProcessor.TickType.SYSTEM.getIndex()] - prevTicks[CentralProcessor.TickType.SYSTEM.getIndex()];
        long idle = ticks[CentralProcessor.TickType.IDLE.getIndex()] - prevTicks[CentralProcessor.TickType.IDLE.getIndex()];
        long iowait = ticks[CentralProcessor.TickType.IOWAIT.getIndex()] - prevTicks[CentralProcessor.TickType.IOWAIT.getIndex()];
        long irq = ticks[CentralProcessor.TickType.IRQ.getIndex()] - prevTicks[CentralProcessor.TickType.IRQ.getIndex()];
        long softirq = ticks[CentralProcessor.TickType.SOFTIRQ.getIndex()] - prevTicks[CentralProcessor.TickType.SOFTIRQ.getIndex()];
        long steal = ticks[CentralProcessor.TickType.STEAL.getIndex()] - prevTicks[CentralProcessor.TickType.STEAL.getIndex()];
        long totalCpu = user + nice + system + idle + iowait + irq + softirq + steal;
        String cpuUsed = String.format("%.1f%%", 100d * (totalCpu - idle) / totalCpu);
        // 内存
        GlobalMemory memory = hal.getMemory();
        long totalMemory = memory.getTotal(); // 总内存
        long availableMemory = memory.getAvailable(); // 未使用
        long usedMemory = totalMemory - availableMemory; // 已使用
        double memoryUsage = (double) usedMemory / totalMemory * 100; // 使用率
        String memoryUsed = String.format("%.1f%%", memoryUsage);
        // jvm内存
        MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean();
        MemoryUsage heapMemoryUsage = memoryBean.getHeapMemoryUsage();
        long jvmMaxMemory = heapMemoryUsage.getMax(); // 最大内存
        long jvmUsedMemory = heapMemoryUsage.getUsed(); // 已使用
        long jvmFreeMemory = heapMemoryUsage.getMax() - heapMemoryUsage.getUsed(); // 未使用
        double jvmMemoryUsage = (double) jvmUsedMemory / jvmMaxMemory * 100; // 使用率
        String jvmMemoryUsed = String.format("%.1f%%", jvmMemoryUsage);
        // jvm 信息
        // 获取 RuntimeMXBean 实例
        RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();
        String jvmName = runtimeMXBean.getVmName(); // JVM 名称
        String jvmVersion = System.getProperty("java.version");// 版本
        long jvmStartTime = runtimeMXBean.getStartTime(); // JVM 启动时间
        long jvmUpTime = runtimeMXBean.getUptime(); // JVM 运行时间
        String jvmHome = System.getProperty("java.home"); // JVM 安装路径
        String projectPath = System.getProperty("user.dir"); // 项目运行路径
        // 获取 JVM 启动参数
        StringBuilder jvmArgs = new StringBuilder();
        for (String arg : runtimeMXBean.getInputArguments()) {
            jvmArgs.append(arg).append(" ");
        }

        Map<String, Object> result = new HashMap<String, Object>();
        // 系统
        result.put("systemName", systemName); // 系统名
        result.put("hostName", hostName); // HostName
        result.put("upTime", getTimeStr(upTime)); // 系统运行时长
        result.put("ipv4", InetAddress.getLocalHost().getHostAddress()); // IP地址
        result.put("osArch", System.getProperty("os.arch")); // 系统架构
        // cpu
        result.put("cpuName", cpuName); // cpu名称
        result.put("physicalCoreCount", physicalCoreCount);// 物理核心数
        result.put("logicalCoreCount", logicalCoreCount); // 逻辑核心数
        result.put("maxFrequencyStr", maxFrequencyStr); // 最大频率
        result.put("cpuUsed", cpuUsed); // 最大频率
        // 内存
        result.put("totalMemory", formatBytes(totalMemory)); // 总内存
        result.put("usedMemory", formatBytes(usedMemory)); // 已使用
        result.put("availableMemory", formatBytes(availableMemory)); // 未使用
        result.put("memoryUsed", memoryUsed); // 使用率
        // jvm 内存
        result.put("jvmMaxMemory", formatBytes(jvmMaxMemory)); // 最大内存
        result.put("jvmUsedMemory", formatBytes(jvmUsedMemory)); // 已使用
        result.put("jvmFreeMemory", formatBytes(jvmFreeMemory)); // 未使用
        result.put("jvmMemoryUsed", jvmMemoryUsed); // 使用率
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒");
        // jvm 信息
        result.put("jvmName", jvmName); // JVM 名称
        result.put("jvmVersion", jvmVersion);// 版本
        result.put("jvmStartTime", dateFormat.format(new Date(jvmStartTime))); // JVM 启动时间
        result.put("jvmUpTime", getTimeStr(jvmUpTime / 1000)); // JVM 运行时间
        result.put("jvmHome", jvmHome); // JVM 安装路径
        result.put("projectPath", projectPath); // 项目运行路径
        result.put("jvmArgs", jvmArgs.toString()); // JVM 启动参数

        return AjaxResult.success(result);
    }
}
